package web_api

import (
	"context"
	"fmt"
	"github.com/gin-gonic/gin"
	"net/http"
	"net/http/httputil"
	"platon-tools/go-service/common/constant"
	"platon-tools/go-service/common/util"
	"platon-tools/go-service/module"
	"platon-tools/go-service/service"
	"strings"
	"sync/atomic"
)

type HttpApi struct {
	ctx    context.Context
	cancel context.CancelFunc

	service *service.Service

	running int32

	addr string

	proxy string
}

func (api *HttpApi) Start(ctx context.Context, config *service.Config, s *service.Service) error {

	fmt.Println("http init start")

	selfCtx, cancel := context.WithCancel(ctx)

	api.ctx = selfCtx
	api.cancel = cancel
	api.service = s

	api.addr = fmt.Sprintf(":%s", config.Http.Port)

	atomic.StoreInt32(&api.running, 1)
	go api.runLoop()

	fmt.Println("http init success")

	return nil
}

const Host = "127.0.0.1:8545"

var simpleHostProxy = httputil.ReverseProxy{
	Director: func(req *http.Request) {
		req.URL.Scheme = "http"
		req.URL.Host = Host
		req.Host = Host
	},
}

func (api *HttpApi) WithHeader(ctx *gin.Context) {
	ctx.Request.Header.Add("requester-uid", "id")
	simpleHostProxy.ServeHTTP(ctx.Writer, ctx.Request)
}

func (api *HttpApi) runLoop() {
	defer api.Close()
	gin.SetMode(gin.ReleaseMode)
	r := gin.Default()

	// 跨域
	r.Use(Cors())
	// 校验token
	r.Use(api.AuthMiddleware())

	// 新建用户
	r.POST("/manager/sys/user/add", api.AddUser)
	// 修改用户信息
	r.POST("/manager/sys/user/edit", api.EditUser)
	// 修改个人信息
	r.POST("/manager/sys/user/editMyself", api.EditMyself)
	// 修改本人密码
	r.POST("/manager/sys/user/editPassword", api.EditPassword)
	// 管理员重置密码
	r.POST("/manager/sys/user/resetPassword", api.ResetPassword)
	// 登陆
	r.POST("/manager/sys/user/login", api.Login)
	// 登陆
	r.GET("/manager/sys/user/logout", api.Logout)
	// 本人用户详情
	r.POST("/manager/sys/user/myself", api.MyselfDetail)
	// 用户详情
	r.POST("/manager/sys/user/detail", api.UserDetail)
	// 用户列表
	r.GET("/manager/sys/user/list", api.UserList)
	// 冻结用户
	r.GET("/manager/sys/user/freeze", api.FreezeUser)
	// 解冻用户
	r.GET("/manager/sys/user/unFreeze", api.UnFreezeUser)
	// 删除用户
	r.GET("/manager/sys/user/delete", api.DeleteUser)

	// 角色列表
	r.GET("/manager/sys/role/list", api.RoleList)
	// 角色详情
	r.GET("/manager/sys/role/get", api.GetRole)
	// 新增角色
	r.POST("/manager/sys/role/add", api.AddRole)
	// 编辑角色
	r.POST("/manager/sys/role/edit", api.EditRole)
	// 删除角色
	r.GET("/manager/sys/role/delete", api.DeleteRole)

	// 节点树形列表
	r.GET("/manager/sys/node/tree", api.NodeTree)
	// 节点列表
	r.GET("/manager/sys/node/list", api.NodeList)
	// 节点详情
	r.GET("/manager/sys/node/detail", api.NodeDetail)
	// 新建节点
	r.POST("/manager/sys/node/add", api.AddNode)
	// 编辑节点
	r.POST("/manager/sys/node/edit", api.EditNode)
	// 删除节点
	r.GET("/manager/sys/node/delete", api.DeleteNode)
	// 谷歌云回调
	r.GET("/manager/sys/node/google", api.GoogleNode)

	// 首页汇总数据
	r.GET("/manager/sys/node/index/total", api.IndexTotal)
	// 单个节点汇总数据
	r.GET("/manager/sys/node/single_total", api.NodeStakingDetail)
	// 节点汇总数据
	r.GET("/manager/sys/node/total", api.StakingTotal)
	// 节点收益折线图
	r.GET("/manager/sys/contract/benefit", api.BenefitLineChart)
	// 周期收益占比
	r.GET("/manager/sys/contract/cycle", api.CycleBenefit)
	// 收益饼图
	r.GET("/manager/sys/contract/funnel", api.FunnelChart)
	// 节点投资分布
	r.GET("/manager/sys/contract/invest", api.InvestTotal)

	// 节点监控汇总数据
	r.GET("/manager/sys/monitor/node/total", api.MonitorNodeTotal)
	// 节点监控列表数据
	r.GET("/manager/sys/monitor/node/list", api.MonitorNodeList)
	// 节点监控详情
	r.GET("/manager/sys/monitor/node/detail", api.MonitorNodeDetail)
	// 折线图
	r.GET("/manager/sys/monitor/node/analysis", api.MonitorAnalysis)

	// 报警策略列表
	r.GET("/manager/sys/alert/list", api.MonitorList)
	// 报警策略详情
	r.GET("/manager/sys/alert/detail", api.MonitorDetail)
	// 新增报警策略
	r.POST("/manager/sys/alert/add", api.AddMonitor)
	// 编辑报警策略
	r.POST("/manager/sys/alert/edit", api.EditMonitor)
	// 启用报警策略
	r.GET("/manager/sys/alert/start", api.StartMonitor)
	// 冻结报警策略
	r.GET("/manager/sys/alert/freeze", api.FreezeMonitor)

	_ = r.Run(api.addr)
}

func (api *HttpApi) IsRunning() bool {
	if atomic.LoadInt32(&api.running) == 1 {
		return true
	}

	return false
}

func (api *HttpApi) Name() string {
	return "HTTPAPI"
}

func (api *HttpApi) Close() error {
	if api.IsRunning() {
		atomic.StoreInt32(&api.running, 0)
		api.cancel()
	}

	return nil
}

func Cors() gin.HandlerFunc {
	return func(c *gin.Context) {
		method := c.Request.Method

		c.Header("Access-Control-Allow-Origin", "*")
		c.Header("Access-Control-Allow-Headers", "Content-Type,AccessToken,X-CSRF-Token, Authorization, session_id")
		c.Header("Access-Control-Allow-Methods", "POST, GET, OPTIONS")
		c.Header("Access-Control-Expose-Headers", "Content-Length, Access-Control-Allow-Origin, Access-Control-Allow-Headers, Content-Type")
		c.Header("Access-Control-Allow-Credentials", "true")

		//放行所有OPTIONS方法
		if method == "OPTIONS" {
			c.AbortWithStatus(http.StatusNoContent)
		}
		// 处理请求
		c.Next()
	}
}

var DoNotNeedLogin = []string{
	"/manager/sys/user/login",
	"",
}

// 定义检验session中间件
func (api *HttpApi) AuthMiddleware() gin.HandlerFunc {
	return func(c *gin.Context) {
		// 登陆请求直接放过
		if url := c.Request.URL.String(); util.InArray(url, DoNotNeedLogin) {
			c.Next()
			return
		}
		sessionId := c.GetHeader("session_id")
		if sessionId == "" {
			c.Abort()
			c.JSON(http.StatusUnauthorized, util.FailResponse(constant.ERROR_CODE_1103, constant.ERROR_MESSAGE_1103))
			return
		}
		r := api.service.ModuleByName("REDIS")
		if db, ok := r.(*module.RedisDB); ok {
			reply, err := db.GetString(sessionId)
			if err != nil {
				c.Abort()
				c.JSON(http.StatusUnauthorized, util.FailResponse(constant.ERROR_CODE_1103, constant.ERROR_MESSAGE_1103))
				return
			}
			// session续命
			_ = db.SetSession(sessionId, reply)

			res := strings.Split(reply, "|")

			// user_id写入上下文
			c.Set("login_id", res[0])
			c.Set("login_name", res[1])

			c.Next()
		}
	}
}
